//
// Created by Martin on 2023/3/31.
//

#ifndef MUDUO_COMMON_H
#define MUDUO_COMMON_H

#include <type_traits>
#include <memory>

namespace ftp {
namespace details {

// make_unique support for pre c++14

#if __cplusplus >= 201402L // C++14 and beyond
using std::enable_if_t;
using std::make_unique;
#else
template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B, T>::type;

template<typename T>
struct is_unbounded_array : std::false_type {};
template<typename T>
struct is_unbounded_array<T[]> : std::true_type {};

template<typename T>
struct is_bounded_array : public std::false_type {};
template<typename T, std::size_t N>
struct is_bounded_array<T[N]> : std::true_type {};

// regular pointer
template<typename T, typename... Args>
enable_if_t<!std::is_array<T>::value, std::unique_ptr<T>>
make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

// flexible array
template<typename T>
enable_if_t<std::is_array<T>::value && std::extent<T>::value == 0, std::unique_ptr<T>>
make_unique(size_t size) {
    typedef typename std::remove_extent<T>::type U;
    return std::unique_ptr<T>(new U[size]());
}

// delete fixed array
template<typename T, class... Args>
enable_if_t<std::extent<T>::value != 0, void>
make_unqiue(Args&& ...) = delete;

#if 0
template<typename T, typename... Args>
enable_if_t<!std::is_array<T>::value, std::unique_ptr<T>>
make_unique(Args &&... args)
{
    static_assert(!std::is_array<T>::value, "arrays not supported");
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

template<typename T>
enable_if_t<is_unbounded_array<T[]>::value, std::unique_ptr<T>>
make_unique(size_t n)
{
    static_assert(std::is_array<T>::value, "make_unique arrays");
    return std::unique_ptr<T>(new std::remove_extent<T>[n]());
}

//template<typename T, typename... Args>
//std::enable_if<details::is_bounded_array<T>::value> make_unique(Args&&...) = delete;
#endif

#endif

} // namespace details
} // namespace ftp

#endif //MUDUO_COMMON_H
